<!--
* @fileName c-tree.vue
* @author caoke
* @date 2023/10/09 17:34:33
* @version V1.0.0
* @description 地址选择器
!-->
<template>
  <div>
    <div class="tree-container">
      <div class="left">
        <div class="header">
          <!-- 复选框，点击事件 -->
          <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="selectAll">全选</el-checkbox>
          <el-input class="input" placeholder="请输入关键词" v-model="filterText"></el-input>
        </div>
        <el-tree :filter-node-method="filterNode" ref="tree" node-key="adcode" @check="handleCheck"
          @check-change="handleCheckChange" :data="leftTreeList" :props="defaultProps" show-checkbox
          @node-click="handleNodeClick" highlight-current></el-tree>
      </div>
      <div class="right">
        <div class="header">
          <!-- 复选框，点击事件 -->
          <el-checkbox :disabled="!checkAll && !isIndeterminate" v-model="checkAll" :indeterminate="isIndeterminate"
            @change="setSelectAll(false)">已选</el-checkbox>
        </div>
        <el-tree :filter-node-method="rightFilterNode" ref="rightTree" node-key="adcode" @check="rightHandleCheck"
          @check-change="handleCheckChange" :data="rightTreeList" :props="defaultProps" show-checkbox
          @node-click="handleNodeClick" highlight-current></el-tree>
      </div>
    </div>


    <!-- <div class="buttons">
      <el-button @click="getCheckedNodes">通过 node 获取</el-button>
      <el-button @click="getCheckedKeys">通过 key 获取</el-button>
      <el-button @click="setCheckedNodes">通过 node 设置</el-button>
      <el-button @click="setCheckedKeys">通过 key 设置</el-button>
      <el-button @click="resetChecked">清空</el-button>
      <el-button @click="filterText">过滤</el-button>
    </div> -->
  </div>
</template>

<script>
export default {
  name: "",
  props: {
    data: Array,
  },
  data() {
    return {
      defaultProps: {
        children: "children",
        label: "name",
      },
      leftTreeList: JSON.parse(JSON.stringify(this.data)),
      rightTreeList: JSON.parse(JSON.stringify(this.data)),
      filterText: '',
      // tree是否全选，复选框默认状态（）
      checkAll: false,
      mydata: [],
      isIndeterminate: false,
    };
  },
  watch: {
    data: {
      // 每个属性值发生变化就会调用这个函数
      handler(newVal, oldVal) {
        this.mydata = this.convertTreeData(JSON.parse(JSON.stringify(newVal)))//因为下面要判断数组长度，树的结构里包含children，所以要将其展开。
      },
      // 立即处理 进入页面就触发
      immediate: true,
      // 深度监听 属性的变化
      deep: true
    },
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },
  mounted() {
    this.$refs.rightTree.filter([])
  },
  methods: {
    // 公开方法 start
    // 设置全选状态
    setSelectAll(checkAll = true) {
      this.checkAll = checkAll
      this.selectAll()
    },
    //获取全选状态
    getSelectAll() {
      return this.checkAll
    },
    //获取格式化后的地区数据
    getValue() {
      let arr = []
      let areacodeList = this.getCheckedNodes()

      if (this.getSelectAll()) {//如果全选返回全国
        let obj = {
          name: '全国',
          adcode: '000000',
        }
        arr.push(obj)
      } else {//如果二级全选只保留一级
        console.log(areacodeList);
        console.log(this.rightTreeList);
        this.rightTreeList.forEach(i => {
          if (i.selectAll) {
            arr.push(i)
          } else if (i.checked) {
            arr.push(i)
          } else if (i.children && i.children.length > 0) {
            i.children.forEach(j => {
              if (j.checked) {
                arr.push(j)
              }
            })
          }
        })
      }

      return arr
    },

    // 公开方法 end
    // tree 结构转化成一维数组
    convertTreeData(treeList = []) {
      let children = this.defaultProps.children
      for (let i = 0; i < treeList.length; i++) {
        if (treeList[i][children] != undefined) {
          const temp = treeList[i][children]
          delete treeList[i][children]
          treeList = treeList.concat(temp)
        }
      }
      return treeList
    },
    // 全选反选
    selectAll() {
      if (this.checkAll) {
        this.setCheckedNodes(this.leftTreeList)
      } else {
        this.setCheckedNodes([])
      }
      this.isIndeterminate = false;
    },
    //过滤只剩选中的
    rightFilterNode(value, data) {
      return value.indexOf(data.adcode) !== -1;
    },
    handleCheck(data, checked,) {
      console.log('当复选框被点击的时候触发', data, checked,);//传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象，包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
      this.$refs.rightTree.setCheckedKeys(checked.checkedKeys)
      this.$refs.rightTree.filter(checked.checkedKeys);

      this.checkChange(checked.checkedKeys)
    },
    rightHandleCheck(data, checked,) {
      console.log('当右侧复选框被点击的时候触发', data, checked,);
      this.$refs.tree.setCheckedKeys(checked.checkedKeys)
      this.$refs.rightTree.filter(checked.checkedKeys);
      this.checkChange(checked.checkedKeys)

    },
    checkChange(checkedKeys) {
      //与全选关联起来，判断是否全部选中还是部分选中
      let checkedCount = checkedKeys.length;
      this.checkAll = checkedCount === this.mydata.length
      this.isIndeterminate = checkedCount > 0 && checkedCount < this.mydata.length
      this.isRightTreeDisabled(this.rightTreeList)
    },
    handleCheckChange(data, checked, indeterminate) {
      // console.log('节点选中状态发生变化时的回调', data, checked, indeterminate);//共三个参数，依次为：传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点
    },
    handleNodeClick(data) {
      // console.log('节点被点击时的回调', data);
    },



    // TODO 示例方法
    getCheckedNodes() {
      // console.log('通过 node 获取', this.$refs.tree.getCheckedNodes());
      return this.$refs.tree.getCheckedNodes()
    },
    getCheckedKeys() {
      // console.log('通过 key 获取', this.$refs.tree.getCheckedKeys());
      return this.$refs.tree.getCheckedKeys()
    },
    isRightTreeDisabled(treeList = []) {
      let checkedKeys = this.getCheckedKeys()
      treeList.forEach(i => {
        i.checked = checkedKeys.includes(i.adcode) ? true : false
        if (i.children && i.children.length > 0) {
          let selectAll = i.children.every(j => checkedKeys.includes(j.adcode))
          i.disabled = !selectAll ? true : false
          i.selectAll = selectAll
          i.children.forEach(j => {
            j.checked = checkedKeys.includes(j.adcode) ? true : false
          })
        }

      })
    },
    // 设置树选中状态
    setCheckedNodes(Nodes = []) {
      this.$refs.tree.setCheckedNodes(Nodes)
      if (this.$refs.rightTree) {//如果有右侧树设置右侧树选中状态
        this.setRightCheckedNodes(Nodes)
        // TODO 设置二级未全选中禁用一级选项
        this.isRightTreeDisabled(this.rightTreeList)
      }
      // this.$refs.tree.setCheckedNodes([
      //   {
      //     adcode: 5,
      //     label: "二级 2-1",
      //   },
      //   {
      //     adcode: 9,
      //     label: "三级 1-1-1",
      //   },
      // ]);
    },
    setRightCheckedNodes(Nodes) {
      this.$refs.rightTree.setCheckedNodes(Nodes)
      this.$refs.rightTree.filter(this.$refs.rightTree.getCheckedKeys())
    },

    // 设置树选中状态 
    setCheckedKeys(checkedKeys = []) {
      this.$refs.tree.setCheckedKeys(checkedKeys);
      if (this.$refs.rightTree) {//如果有右侧树设置右侧树选中状态
        this.setRightCheckedKeys(checkedKeys)
        // TODO 设置二级未全选中禁用一级选项
        this.isRightTreeDisabled(this.rightTreeList)
      }

    },
    setRightCheckedKeys(checkedKeys = []) {
      this.$refs.rightTree.setCheckedKeys(checkedKeys)
      this.$refs.rightTree.filter(checkedKeys);
    },
    //重置选中状态
    resetChecked() {
      this.$refs.tree.setCheckedKeys([]);
    },

    filterNode(value, data) {
      console.log('filterNode', value, data);
      if (!value) return true;
      return data[this.defaultProps.label].indexOf(value) !== -1;
    },
  },
};
</script>
<style lang='scss' scoped>
.tree-container {
  display: flex;

  .left {
    flex: 1;

    .header {
      // padding: 8px;
      height: 40px;
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;

      .input {
        margin-left: 10px;
      }
    }
  }

  .right {
    flex: 1;

    .header {
      padding-left: 8px;
      height: 40px;
      width: 100%;
      display: flex;
      justify-content: start;
      align-items: center;
    }
  }
}
</style>